/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package naivebayes;

import TextManager.FilesReader;
import TextManager.Vocabulary;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 *
 * @author Jaime
 */
public class ModelsGenerator {
    
    private int numberOfGroups;
    private int docsPerGroups;
    private List<DocumentsGroup> documentGroups;
    private List<Model> models;
    private Vocabulary vocabulary;
    
    
     /**
     * Default constructor.
     * @param numberOfGroups Number of groups for cross-validation.
     * @param documents The documents.
     * @prerequirement number of documents must be multiple of the number of groups.
     */
     
    public ModelsGenerator(int numberOfGroups, List<File> positiveDocuments, 
            List<File> negativeDocuments) throws FileNotFoundException, IOException
    {
        assert numberOfGroups > 1 : "number of groups must be greater than one";
        assert negativeDocuments.size() % numberOfGroups == 0 : "Number of "
                + "negative files should be multiple of the number of groups";
        assert positiveDocuments.size() % numberOfGroups == 0 : "Number of "
                + "positive files should be multiple of the number of groups";
        
        
        this.numberOfGroups = numberOfGroups;
        this.docsPerGroups = (positiveDocuments.size()+negativeDocuments.size())/numberOfGroups;
        documentGroups = new ArrayList<DocumentsGroup>(numberOfGroups);
        models = new ArrayList<Model>(numberOfGroups);
        
        int negativeFilesPerGroup = negativeDocuments.size()/numberOfGroups;
        int positiveFilesPerGroup = positiveDocuments.size()/numberOfGroups;
                
        vocabulary = new Vocabulary();
        
        for(int i = 0; i < numberOfGroups; i++)
        {
            DocumentsGroup group = new DocumentsGroup(vocabulary);
            
            documentGroups.add(group);
           
            addDocuments(group, positiveDocuments, negativeDocuments, positiveFilesPerGroup, negativeFilesPerGroup);
            
                       
        }     
        
        
        
        //System.out.println(voc);   
        
        for(int i = 0; i < numberOfGroups; i++)
        {
            Model model = new Model(documentGroups.get(i), vocabulary);
            models.add(model);
            
            for(int j = 0; j < numberOfGroups; j++)
            {
                if(i != j)
                {
                    model.addLearningGroup(documentGroups.get(j));
                }
            }
            
        }
        
    }

    private void addDocuments(DocumentsGroup group, List<File> positiveDocuments, 
            List<File> negativeDocuments, int positiveNumberPerGroup, int negativeNumberPerGroup) throws FileNotFoundException, 
            IOException {
        
        Random rand = new Random();
        FilesReader fr = new FilesReader(group);
        
        for(int i = 0; i < positiveNumberPerGroup; i++)
        {            
            
                int index = rand.nextInt(positiveDocuments.size());
                fr.read(positiveDocuments.remove(index), true);                 
        }
        
        for(int i = 0; i < negativeNumberPerGroup; i++)
        {            
            
                int index = rand.nextInt(negativeDocuments.size());
                fr.read(negativeDocuments.remove(index), false);                 
        }
        
        
    }

    public void trainAndTestAll() throws FileNotFoundException, IOException
    {
        for(Model m:models)
        {
            m.train();
            m.performTest();
        }
    }
    

    void storeResults(String resultsFile) throws IOException {
        File file = new File(resultsFile);
        
        FileWriter outFile = new FileWriter(file);
        PrintWriter out = new PrintWriter(outFile);
        
        int i = 1;
        
        out.println(models.size()+" were generated.");
        out.println("The vocabulary has "+vocabulary.size()+" words.");
        out.println();
        
        int totalPositions = 0;
        
        List<ConfusionMatrix> confusionMatrices = new ArrayList<ConfusionMatrix>();
        
        for(Model m:models)
        {
            out.println("Model "+i+":");
            out.println(m.analysisToString()+"\n");     
            totalPositions += m.totalPositivePositions() + m.totalNegativePositions();
            confusionMatrices.add(m.getConfusionMatrix());
            i++;
        }
        
        AverageConfusionMatrix acm = new AverageConfusionMatrix(confusionMatrices);
        
        out.println(acm.toString());
        
        out.println("A total of "+totalPositions+" positions.");
        
        out.close();
        outFile.close();
        
    }
    
    
}
